package com.zshan.clinic.admin.service.medical;

import com.fasterxml.jackson.core.type.TypeReference;
import com.zshan.clinic.admin.constant.Constants;
import com.zshan.clinic.admin.entity.dto.OrderDispenseDTO;
import com.zshan.clinic.admin.entity.medical.dispense.RxDrugDispense;
import com.zshan.clinic.admin.entity.medical.dispense.RxInfusionDispense;
import com.zshan.clinic.admin.entity.medical.dispense.RxTcmDispense;
import com.zshan.clinic.admin.entity.medical.dispense.base.*;
import com.zshan.clinic.admin.entity.medical.rx.RxDrug;
import com.zshan.clinic.admin.entity.medical.rx.RxInfusion;
import com.zshan.clinic.admin.entity.medical.rx.base.*;
import com.zshan.clinic.admin.entity.medical.stock.DrugOut;
import com.zshan.clinic.admin.entity.medical.stock.StockOutDTO;
import com.zshan.clinic.admin.entity.vo.*;
import com.zshan.clinic.admin.mapper.medical.SpecOrderDispenseMapper;
import com.zshan.clinic.admin.service.notice.ClinicNoticeService;
import com.zshan.clinic.admin.service.stock.StockDrugService;
import com.zshan.clinic.admin.task.AsyncTaskService;
import com.zshan.clinic.common.constant.CommonConstant;
import com.zshan.clinic.common.enums.*;
import com.zshan.clinic.common.exception.BusinessFailException;
import com.zshan.clinic.common.util.json.JsonUtil;
import com.zshan.clinic.common.util.page.PageInfo;
import com.zshan.clinic.common.util.page.PageUtils;
import com.zshan.clinic.common.util.string.StringUtil;
import com.zshan.clinic.common.util.uuid.IdBuilder;
import com.zshan.clinic.database.dao.OrderDeliveryDetailMapper;
import com.zshan.clinic.database.dao.OrderDeliveryMapper;
import com.zshan.clinic.database.dao.OrderDispenseMapper;
import com.zshan.clinic.database.dao.OrderDispenseRxMapper;
import com.zshan.clinic.database.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDate;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 药房配药和发药
 */
@Service
@Slf4j
public class OrderDispenseService {

    @Autowired
    private OrderDispenseMapper orderDispenseMapper;

    @Autowired
    private OrderDispenseRxMapper orderDispenseRxMapper;

    @Autowired
    private OrderDeliveryMapper orderDeliveryMapper;

    @Autowired
    private OrderDeliveryDetailMapper orderDeliveryDetailMapper;

    @Autowired
    private ClinicMedicalService clinicMedicalService;

    @Autowired
    private SpecOrderDispenseMapper specOrderDispenseMapper;

    @Autowired
    private StockDrugService stockDrugService;

    @Autowired
    private ClinicNoticeService noticeService;

    @Autowired
    private AsyncTaskService asyncTaskService;

    /**
     * 查询患者发药记录
     * @param clinicId
     * @param patientId
     * @param visitDate
     * @param pageNo
     * @param pageSize
     * @return
     */
    public PageInfo<OrderDeliveryPatientVo> getPatientDeliveryList(Long clinicId, Long patientId, LocalDate visitDate, Integer pageNo, Integer pageSize) {
        Long totalCount = specOrderDispenseMapper.getPatientDeliveryCount(clinicId,patientId,visitDate);
        if(StringUtil.isBlank(totalCount)){
            return PageInfo.build();
        }
        List<OrderDeliveryPatientVo> deliveryList = specOrderDispenseMapper.getPatientDeliveryList(clinicId,patientId,visitDate,PageUtils.getOffset(pageNo,pageSize),pageSize);
        return new PageInfo<>(totalCount,deliveryList);
    }

    /**
     * 查询诊所今日药房待发数
     * @param clinicId
     * @return
     */
    public DispenseWaitingVo getWaitingCount(Long clinicId) {
        return specOrderDispenseMapper.getWaitingCount(clinicId,LocalDate.now());
    }


    /**
     * 查询患者发药历史
     * @param clinicId
     * @param patientId
     * @return
     */
    public List<OrderDeliveryDetailVo> getDeliveryHistoryList(Long clinicId, Long patientId, Integer pageNo, Integer pageSize){
        String deliveryStatus = DeliveryStatusEnum.PASS.getValue();
        List<OrderDeliveryDetailVo> orderDeliveryDetailList = specOrderDispenseMapper.getDeliveryDetailList(clinicId,patientId,deliveryStatus,PageUtils.getOffset(pageNo,pageSize),pageSize);
        if(CollectionUtils.isEmpty(orderDeliveryDetailList)){
            return Collections.EMPTY_LIST;
        }
        for(OrderDeliveryDetailVo orderDeliveryDetailVo : orderDeliveryDetailList){
            orderDeliveryDetailVo.setRxList(handleRxList(orderDeliveryDetailVo.getRxList()));
        }
        return orderDeliveryDetailList;
    }

    /**
     * 查询患者配药历史
     * @param clinicId
     * @param patientId
     * @return
     */
    public List<OrderDeliveryDetailVo> getDispenseHistoryList(Long clinicId, Long patientId, Integer pageNo, Integer pageSize){
        List<OrderDeliveryDetailVo> orderDeliveryDetailList = specOrderDispenseMapper.getDeliveryDetailList(clinicId,patientId,null,PageUtils.getOffset(pageNo,pageSize),pageSize);
        if(CollectionUtils.isEmpty(orderDeliveryDetailList)){
            return Collections.EMPTY_LIST;
        }
        for(OrderDeliveryDetailVo orderDeliveryDetailVo : orderDeliveryDetailList){
            orderDeliveryDetailVo.setRxList(handleRxList(orderDeliveryDetailVo.getRxList()));
        }
        return orderDeliveryDetailList;
    }

    /**
     * 查询发药单列表
     * @param clinicId
     * @param patientName
     * @param visitDate
     * @param pageNo
     * @param pageSize
     * @return
     */
    public List<OrderDeliveryPageVo> getDeliveryList(Long clinicId, String patientName, LocalDate visitDate, Integer pageNo, Integer pageSize){
        //方便调试
//        if(visitDate == null){
//            visitDate = LocalDate.now();
//        }
        if(StringUtil.isNotBlank(patientName)){
            visitDate = null;
        }
        return specOrderDispenseMapper.getDeliveryList(clinicId,patientName,visitDate,PageUtils.getOffset(pageNo,pageSize),pageSize);
    }


    /**
     * 查询发药单详情
     * @param clinicId
     * @param orderId
     * @return
     */
    public OrderDeliveryDetailVo getDeliveryDetail(Long clinicId, Long orderId){
        OrderDeliveryDetailVo orderDeliveryDetailVo = specOrderDispenseMapper.getDeliveryDetail(clinicId,orderId);
        if(orderDeliveryDetailVo == null){
            throw new BusinessFailException("发药单不存在");
        }
        orderDeliveryDetailVo.setRxList(handleRxList(orderDeliveryDetailVo.getRxList()));
        return orderDeliveryDetailVo;
    }



    /**
     * 查询配药单列表
     * @param clinicId
     * @param patientName
     * @param visitDate
     * @param pageNo
     * @param pageSize
     * @return
     */
    public List<OrderDispensePageVo> getDispenseList(Long clinicId, String patientName, LocalDate visitDate, Integer pageNo, Integer pageSize){
        //方便调试
//        if(visitDate == null){
//            visitDate = LocalDate.now();
//        }
        if(StringUtil.isNotBlank(patientName)){
            visitDate = null;
        }
        return specOrderDispenseMapper.getDispenseList(clinicId,patientName,visitDate,PageUtils.getOffset(pageNo,pageSize),pageSize);
    }


    /**
     * 查询配药单详情
     * @param clinicId
     * @param orderId
     * @return
     */
    public OrderDispenseDetailVo getDispenseDetail(Long clinicId,Long orderId){
        OrderDispenseDetailVo orderDispenseDetailVo = specOrderDispenseMapper.getDispenseDetail(clinicId,orderId);
        if(orderDispenseDetailVo == null){
            throw new BusinessFailException("配药单不存在");
        }
        orderDispenseDetailVo.setRxList(handleRxList(orderDispenseDetailVo.getRxList()));
        return orderDispenseDetailVo;
    }

    /**
     * 处方的json转实体
     * @param rxList
     * @return
     */
    public List<RxDispenseBase> handleRxList(List<RxDispenseBase> rxList) {
        if(CollectionUtils.isEmpty(rxList)){
            return Collections.emptyList();
        }
        List<RxDispenseBase> returnList = new ArrayList<>();
        for(RxDispenseBase rxBase : rxList){
            String rxType = rxBase.getRxType();
            if(RxTypeEnum.DRUG.getValue().equals(rxType)){
                RxDrugDispense rxDrugDispense = new RxDrugDispense();
                BeanUtils.copyProperties(rxBase,rxDrugDispense);
                rxDrugDispense.setDetailList(JsonUtil.json2Obj(rxBase.getRxJson(),new TypeReference<List<RxDrugDispenseDetail>>() {}));
                returnList.add(rxDrugDispense);
            }else if (RxTypeEnum.INFUSION.getValue().equals(rxType)){
                RxInfusionDispense rxInfusionDispense = new RxInfusionDispense();
                BeanUtils.copyProperties(rxBase,rxInfusionDispense);
                rxInfusionDispense.setGroupList(JsonUtil.json2Obj(rxBase.getRxJson(),new TypeReference<List<RxInfusionDispenseGroup>>() {}));
                returnList.add(rxInfusionDispense);
            }else if (RxTypeEnum.TCM.getValue().equals(rxType)){
                RxTcmDispense rxTcmDispense = new RxTcmDispense();
                BeanUtils.copyProperties(rxBase,rxTcmDispense);
                rxTcmDispense.setTcmInfo(JsonUtil.json2Obj(rxBase.getRxJson(),new TypeReference<RxTcmDispenseInfo>() {}));
                returnList.add(rxTcmDispense);
            }
        }
        return returnList;
    }

    /**
     * 发药单审核
     * 发药单驳回需要操作配药表 : 减少已配
     * 发药单通过需要操作配药表 ：增加已发
     * @param orderDelivery
     */
    @Transactional(rollbackFor = Exception.class)
    public void reviewDelivery(OrderDelivery orderDelivery){
        if(StringUtil.isBlank(orderDelivery.getDeliveryStatus())){
            throw new BusinessFailException("审核状态不能为空");
        }
        if(!DeliveryStatusEnum.isValue(orderDelivery.getDeliveryStatus())){
            throw new BusinessFailException("审核状态错误！");
        }
        if(DeliveryStatusEnum.REJECTED.getValue().equals(orderDelivery.getDeliveryStatus())){
            if(StringUtil.isBlank(orderDelivery.getRefuseReason())){
                throw new BusinessFailException("请添加拒绝原因！");
            }
        }
        OrderDelivery dbOrderDelivery = getDeliveryById(orderDelivery.getOrderId());
        if(dbOrderDelivery == null){
            throw new BusinessFailException("发药单不存在");
        }
        if(!DeliveryStatusEnum.PENDING.getValue().equals(dbOrderDelivery.getDeliveryStatus())){
            throw new BusinessFailException("状态不允许");
        }
        Long updateUserId = orderDelivery.getUpdateUserId();
        String updateBy = orderDelivery.getUpdateBy();
        Date updateTime = new Date();
        dbOrderDelivery.setDeliveryStatus(orderDelivery.getDeliveryStatus());
        dbOrderDelivery.setRefuseReason(orderDelivery.getRefuseReason());
        dbOrderDelivery.setDeliveryUserId(updateUserId);
        dbOrderDelivery.setDeliveryUserName(updateBy);
        dbOrderDelivery.setDeliveryTime(updateTime);
        dbOrderDelivery.setUpdateUserId(updateUserId);
        dbOrderDelivery.setUpdateBy(updateBy);
        dbOrderDelivery.setUpdateTime(updateTime);
        orderDeliveryMapper.updateByPrimaryKeySelective(dbOrderDelivery);
        //发药表最新的处方数据
        List<OrderDeliveryDetail> deliveryDetailList = getOrderDeliveryDetailList(dbOrderDelivery.getOrderId());
        if(CollectionUtils.isEmpty(deliveryDetailList)){
            throw new BusinessFailException("没有找到对应的发药单！");
        }
        //审核通过扣减库存
        if(DeliveryStatusEnum.PASS.getValue().equals(orderDelivery.getDeliveryStatus())){
            StockOutDTO stockOutDTO = new StockOutDTO();
            stockOutDTO.setTransType(DrugTransTypeEnum.DELIVERY.getValue());
            stockOutDTO.setOrderId(dbOrderDelivery.getOrderId());
            stockOutDTO.setOutUserId(dbOrderDelivery.getDeliveryUserId());
            stockOutDTO.setOutUserBy(dbOrderDelivery.getDeliveryUserName());
            stockOutDTO.setDrugOutList(getDrugOutList(deliveryDetailList));
            stockDrugService.stockOut(stockOutDTO);
        }
        //修改配药表数据
        List<Long> rxIdList = deliveryDetailList.stream()
                .map(OrderDeliveryDetail::getRxId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        //配药表最新的处方数据
        List<OrderDispenseRx> orderDispenseRxList = getDispenseRxList(dbOrderDelivery.getDispenseOrderId(),rxIdList);
        if(CollectionUtils.isEmpty(orderDispenseRxList)){
            throw new BusinessFailException("没有找到对应的配药单！");
        }
        //把list转为map，提高检索效率
        Map<Long, OrderDispenseRx> dbRxDispenseMap = orderDispenseRxList.stream()
                .collect(Collectors.toMap(OrderDispenseRx::getRxId, Function.identity()));
        for(OrderDeliveryDetail orderDeliveryRx : deliveryDetailList){
            OrderDispenseRx orderDispenseRx = dbRxDispenseMap.get(orderDeliveryRx.getRxId());
            if(orderDispenseRx == null){
                throw new BusinessFailException("处方不存在");
            }
            handleOrderDeliveryDetail(orderDelivery.getDeliveryStatus(),orderDeliveryRx, orderDispenseRx);
            orderDispenseRx.setUpdateUserId(updateUserId);
            orderDispenseRx.setUpdateBy(updateBy);
            orderDispenseRx.setUpdateTime(updateTime);
        }
        if(DeliveryStatusEnum.REJECTED.getValue().equals(orderDelivery.getDeliveryStatus())){
            OrderDispense orderDispense = getDispenseById(dbOrderDelivery.getDispenseOrderId());
            if(orderDispense == null){
                throw new BusinessFailException("没有找到对应的配药单！");
            }
            orderDispense.setUpdateUserId(updateUserId);
            orderDispense.setUpdateBy(updateBy);
            orderDispense.setUpdateTime(updateTime);
            orderDispense.setDispenseStatus(DispenseStatusEnum.WAITING.getValue());
            orderDispenseMapper.updateByPrimaryKeySelective(orderDispense);
        }
        //批量修改配药表
        specOrderDispenseMapper.updateOrderDispenseRxBatch(orderDispenseRxList);
        if(DeliveryStatusEnum.REJECTED.getValue().equals(orderDelivery.getDeliveryStatus())){
            //如果是审核拒绝，需要发送消息
            ClinicNotice clinicNotice = new ClinicNotice();
            clinicNotice.setEmpId(dbOrderDelivery.getDispenseUserId());
            clinicNotice.setNoticeName(Constants.NOTICE_NAME_ORDER_REVIEW);
            clinicNotice.setNoticeContent(String.format(Constants.NOTICE_CONTENT_ORDER_REVIEW,"发药",dbOrderDelivery.getOrderNo()));
            clinicNotice.setClinicId(dbOrderDelivery.getClinicId());
            noticeService.addNotice(clinicNotice);
        }
        //审核通过统计发药数
        if(DeliveryStatusEnum.PASS.getValue().equals(orderDelivery.getDeliveryStatus())){
            //统计诊所今日营收
            StatClinicIncomeDaily statClinicIncomeDaily = new StatClinicIncomeDaily();
            statClinicIncomeDaily.setClinicId(dbOrderDelivery.getClinicId());
            statClinicIncomeDaily.setDeliveryCount(CommonConstant.DEFAULT_1);
            asyncTaskService.asyncSaveOrUpdateClinicIncome(statClinicIncomeDaily);
        }
    }

    /**
     * 药品出库
     * @param deliveryDetailList
     * @return
     */
    /**
     * 药品出库
     * @param deliveryDetailList
     * @return
     */
    public List<DrugOut> getDrugOutList(List<OrderDeliveryDetail> deliveryDetailList) {
        Map<String, DrugOut> mergeMap = new LinkedHashMap<>(); // 保持顺序
        for (OrderDeliveryDetail orderDeliveryRx : deliveryDetailList) {
            String rxType = orderDeliveryRx.getRxType();
            String deliveryRxJsonStr = orderDeliveryRx.getRxJson();
            if (RxTypeEnum.DRUG.getValue().equals(rxType)) {
                List<RxDrugDispenseDetail> rxDrugDeliveryDetailList =
                        StringUtils.hasText(deliveryRxJsonStr)
                                ? JsonUtil.json2Obj(deliveryRxJsonStr, new TypeReference<List<RxDrugDispenseDetail>>() {})
                                : new ArrayList<>();
                if (CollectionUtils.isEmpty(rxDrugDeliveryDetailList)) {
                    throw new BusinessFailException("处方发药数据错误！");
                }
                for (RxDrugDispenseDetail rxDrugDeliveryDetail : rxDrugDeliveryDetailList) {
                    String key = rxDrugDeliveryDetail.getDrugId() + "-" + orderDeliveryRx.getStorageId();
                    DrugOut drugOut = mergeMap.computeIfAbsent(key, k -> {
                        DrugOut d = new DrugOut();
                        d.setDrugId(rxDrugDeliveryDetail.getDrugId());
                        d.setDrugName(rxDrugDeliveryDetail.getDrugName());
                        d.setStorageId(orderDeliveryRx.getStorageId());
                        d.setMinPackQty(rxDrugDeliveryDetail.getMinPackQty());
                        d.setStockQty(CommonConstant.DEFAULT_0);
                        d.setMinStockQty(CommonConstant.DEFAULT_0);
                        return d;
                    });
                    if (YesOrNoEnum.YES.getValue().equals(rxDrugDeliveryDetail.getIsSplit())) {
                        drugOut.setMinStockQty(
                                drugOut.getMinStockQty() + rxDrugDeliveryDetail.getCurrentDeliveryQty()
                        );
                    } else {
                        drugOut.setStockQty(
                                drugOut.getStockQty() + rxDrugDeliveryDetail.getCurrentDeliveryQty()
                        );
                    }
                }

            } else if (RxTypeEnum.TCM.getValue().equals(rxType)) {
                RxTcmDispenseInfo rxTcmDeliveryInfo =
                        StringUtils.hasText(deliveryRxJsonStr)
                                ? JsonUtil.json2Obj(deliveryRxJsonStr, new TypeReference<RxTcmDispenseInfo>() {})
                                : new RxTcmDispenseInfo();
                if (rxTcmDeliveryInfo == null) {
                    throw new BusinessFailException("处方发药数据错误！");
                }
                for (RxTcmDetail rxTcmDetail : rxTcmDeliveryInfo.getDetailList()) {
                    String key = rxTcmDetail.getDrugId() + "-" + orderDeliveryRx.getStorageId();
                    DrugOut drugOut = mergeMap.computeIfAbsent(key, k -> {
                        DrugOut d = new DrugOut();
                        d.setDrugId(rxTcmDetail.getDrugId());
                        d.setDrugName(rxTcmDetail.getDrugName());
                        d.setStorageId(orderDeliveryRx.getStorageId());
                        d.setMinPackQty(rxTcmDetail.getMinPackQty());
                        d.setStockQty(CommonConstant.DEFAULT_0);
                        d.setMinStockQty(CommonConstant.DEFAULT_0);
                        return d;
                    });
                    if (YesOrNoEnum.YES.getValue().equals(rxTcmDetail.getIsSplit())) {
                        drugOut.setMinStockQty(
                                drugOut.getMinStockQty() + rxTcmDetail.getTotalOutQty()
                        );
                    } else {
                        drugOut.setStockQty(
                                drugOut.getStockQty() + rxTcmDetail.getTotalOutQty()
                        );
                    }
                }

            } else if (RxTypeEnum.INFUSION.getValue().equals(rxType)) {
                List<RxInfusionDispenseGroup> rxInfusionDeliveryGroupList =
                        StringUtils.hasText(deliveryRxJsonStr)
                                ? JsonUtil.json2Obj(deliveryRxJsonStr, new TypeReference<List<RxInfusionDispenseGroup>>() {})
                                : new ArrayList<>();
                if (CollectionUtils.isEmpty(rxInfusionDeliveryGroupList)) {
                    throw new BusinessFailException("处方发药数据错误！");
                }
                for (RxInfusionDispenseGroup group : rxInfusionDeliveryGroupList) {
                    for (RxInfusionDispenseGroupDetail detail : group.getDetailList()) {
                        String key = detail.getDrugId() + "-" + orderDeliveryRx.getStorageId();
                        DrugOut drugOut = mergeMap.computeIfAbsent(key, k -> {
                            DrugOut d = new DrugOut();
                            d.setDrugId(detail.getDrugId());
                            d.setDrugName(detail.getDrugName());
                            d.setStorageId(orderDeliveryRx.getStorageId());
                            d.setMinPackQty(detail.getMinPackQty());
                            d.setStockQty(CommonConstant.DEFAULT_0);
                            d.setMinStockQty(CommonConstant.DEFAULT_0);
                            return d;
                        });
                        if (YesOrNoEnum.YES.getValue().equals(detail.getIsSplit())) {
                            drugOut.setMinStockQty(
                                    drugOut.getMinStockQty() + detail.getCurrentDeliveryQty()
                            );
                        } else {
                            drugOut.setStockQty(
                                    drugOut.getStockQty() + detail.getCurrentDeliveryQty()
                            );
                        }
                    }
                }
            }
        }
        // 返回 List
        return new ArrayList<>(mergeMap.values());
    }



    /**
     * 根据审核状态回写配药表数据
     * @param deliveryStatus
     * @param orderDeliveryRx
     * @param orderDispenseRx
     */
    public void handleOrderDeliveryDetail(String deliveryStatus,OrderDeliveryDetail orderDeliveryRx, OrderDispenseRx orderDispenseRx) {
        String rxType = orderDeliveryRx.getRxType();
        //发药的处方数据
        String deliveryRxJsonStr = orderDeliveryRx.getRxJson();
        //配药的处方数据
        String dispenseRxJsonStr = orderDispenseRx.getRxJson();
        if (RxTypeEnum.DRUG.getValue().equals(rxType)) {
            orderDispenseRx.setRxJson(JsonUtil.obj2Json(handleOrderDeliveryDrug(deliveryStatus, deliveryRxJsonStr, dispenseRxJsonStr)));
            if(DeliveryStatusEnum.REJECTED.getValue().equals(deliveryStatus)){
                //如果驳回了，需要设置配药状态
                orderDispenseRx.setDispenseStatus(DispenseStatusEnum.WAITING.getValue());
            }
        } else if (RxTypeEnum.TCM.getValue().equals(rxType)) {
            orderDispenseRx.setRxJson(JsonUtil.obj2Json(handleOrderDeliveryTcm(deliveryStatus, deliveryRxJsonStr, dispenseRxJsonStr)));
            if(DeliveryStatusEnum.REJECTED.getValue().equals(deliveryStatus)){
                //如果驳回了，需要设置配药状态
                orderDispenseRx.setDispenseStatus(DispenseStatusEnum.WAITING.getValue());
            }
        } else if (RxTypeEnum.INFUSION.getValue().equals(rxType)) {
            orderDispenseRx.setRxJson(JsonUtil.obj2Json(handleOrderDeliveryInfusion(deliveryStatus, deliveryRxJsonStr, dispenseRxJsonStr)));
            if(DeliveryStatusEnum.REJECTED.getValue().equals(deliveryStatus)){
                //如果驳回了，需要设置配药状态
                orderDispenseRx.setDispenseStatus(DispenseStatusEnum.WAITING.getValue());
            }
        }
    }


    /**
     * 回写成药处方
     * @param deliveryRxJsonStr
     * @param dispenseRxJsonStr
     */
    public List<RxDrugDispenseDetail> handleOrderDeliveryDrug(String deliveryStatus,String deliveryRxJsonStr, String dispenseRxJsonStr) {
        // 发药表的成药处方数据
        List<RxDrugDispenseDetail> rxDrugDeliveryDetailList =
                StringUtils.hasText(deliveryRxJsonStr)
                        ? JsonUtil.json2Obj(deliveryRxJsonStr, new TypeReference<List<RxDrugDispenseDetail>>() {})
                        : new ArrayList<>();
        if (CollectionUtils.isEmpty(rxDrugDeliveryDetailList)) {
            throw new BusinessFailException("处方发药数据错误！");
        }
        // 配药表的成药处方数据
        List<RxDrugDispenseDetail> rxDrugDispenseDetailList =
                StringUtils.hasText(dispenseRxJsonStr)
                        ? JsonUtil.json2Obj(dispenseRxJsonStr, new TypeReference<List<RxDrugDispenseDetail>>() {})
                        : new ArrayList<>();
        if (CollectionUtils.isEmpty(rxDrugDispenseDetailList)) {
            throw new BusinessFailException("处方配药数据错误！");
        }
        // 配药表需要修改的处方数据
        for (RxDrugDispenseDetail rxDrugDeliveryDetail : rxDrugDeliveryDetailList) {
            // 配药表对应明细
            RxDrugDispenseDetail rxDrugDispenseDetail = getRxDrugDispenseDetail(rxDrugDeliveryDetail.getDrugId(), rxDrugDispenseDetailList);
            if (rxDrugDispenseDetail == null) {
                throw new BusinessFailException("没有找到对应的配药单中的药品数据，请核对发药单！");
            }
            // 本次发药
            Integer currentDeliveryQty = rxDrugDeliveryDetail.getCurrentDeliveryQty();
            if (currentDeliveryQty == null || currentDeliveryQty <= 0) {
                throw new BusinessFailException("本次发药必须为正整数！");
            }
            //发药单中记录的总的待发
            Integer pendingDeliveryQty = rxDrugDeliveryDetail.getDispenseQty();
            if(currentDeliveryQty > pendingDeliveryQty){
                throw new BusinessFailException("本次发药不能大于配药数量！");
            }
            if(DeliveryStatusEnum.PASS.getValue().equals(deliveryStatus)){
                //审核通过 增加已发 减少待发
                // 增加已发
                rxDrugDispenseDetail.setDeliveryQty(rxDrugDispenseDetail.getDeliveryQty() + currentDeliveryQty);
            }else {
                //审核拒绝 增加待配 减少已配
                // 减少已配
                rxDrugDispenseDetail.setDispenseQty(rxDrugDispenseDetail.getDispenseQty() - currentDeliveryQty);
            }
        }
        return rxDrugDispenseDetailList;
    }

    /**
     * 回写输液处方
     * @param deliveryStatus
     * @param deliveryRxJsonStr
     * @param dispenseRxJsonStr
     */
    public List<RxInfusionDispenseGroup> handleOrderDeliveryInfusion(String deliveryStatus, String deliveryRxJsonStr, String dispenseRxJsonStr) {
        // 发药表数据
        List<RxInfusionDispenseGroup> rxInfusionDeliveryGroupList =
                StringUtils.hasText(deliveryRxJsonStr)
                        ? JsonUtil.json2Obj(deliveryRxJsonStr, new TypeReference<List<RxInfusionDispenseGroup>>() {})
                        : new ArrayList<>();
        if (CollectionUtils.isEmpty(rxInfusionDeliveryGroupList)) {
            throw new BusinessFailException("处方发药数据错误！");
        }
        // 配药表数据
        List<RxInfusionDispenseGroup> rxInfusionDispenseGroupList =
                StringUtils.hasText(dispenseRxJsonStr)
                        ? JsonUtil.json2Obj(dispenseRxJsonStr, new TypeReference<List<RxInfusionDispenseGroup>>() {})
                        : new ArrayList<>();
        if (CollectionUtils.isEmpty(rxInfusionDispenseGroupList)) {
            throw new BusinessFailException("处方配药数据错误！");
        }
        for (RxInfusionDispenseGroup rxInfusionDeliveryGroup : rxInfusionDeliveryGroupList) {
            // 配药表输液处方组数据
            RxInfusionDispenseGroup rxInfusionDispenseGroup = getRxInfusionDispenseGroup(rxInfusionDeliveryGroup.getGroupName(), rxInfusionDispenseGroupList);
            // 发药表输液处方组内药品集合
            List<RxInfusionDispenseGroupDetail> rxInfusionDeliveryGroupDetailList = rxInfusionDeliveryGroup.getDetailList();
            if (CollectionUtils.isEmpty(rxInfusionDeliveryGroupDetailList)) {
                throw new BusinessFailException("没有找到发药单中的药品数据，请核对发药单！");
            }
            for (RxInfusionDispenseGroupDetail rxInfusionDeliveryGroupDetail : rxInfusionDeliveryGroupDetailList) {
                // 配药表对应明细
                RxInfusionDispenseGroupDetail rxInfusionDispenseGroupDetail =
                        getRxInfusionDispenseGroupDetail(rxInfusionDeliveryGroupDetail.getDrugId(), rxInfusionDispenseGroup);
                if (rxInfusionDispenseGroupDetail == null) {
                    throw new BusinessFailException("没有找到对应的配药单中的药品数据，请核对发药单！");
                }
                // 本次发药
                Integer currentDeliveryQty = rxInfusionDeliveryGroupDetail.getCurrentDeliveryQty();
                if (currentDeliveryQty == null || currentDeliveryQty <= 0) {
                    throw new BusinessFailException("本次发药必须为正整数！");
                }
                //发药单中记录的总的待发
                Integer pendingDeliveryQty = rxInfusionDeliveryGroupDetail.getDispenseQty();
                if(currentDeliveryQty > pendingDeliveryQty){
                    throw new BusinessFailException("本次发药不能大于配药数量！");
                }
                if(DeliveryStatusEnum.PASS.getValue().equals(deliveryStatus)){
                    //审核通过 增加已发 减少待发
                    // 增加已发
                    rxInfusionDispenseGroupDetail.setDeliveryQty(rxInfusionDispenseGroupDetail.getDeliveryQty() + currentDeliveryQty);
                }else {
                    //审核拒绝 增加待配 减少已配
                    // 更新组的配药状态减少已配
                    rxInfusionDispenseGroup.setDispenseStatus(DispenseStatusEnum.WAITING.getValue());
                    rxInfusionDispenseGroupDetail.setDispenseQty(rxInfusionDispenseGroupDetail.getDispenseQty() - currentDeliveryQty);
                }
            }
        }
        return rxInfusionDispenseGroupList;
    }

    /**
     * 回写中药处方
     * @param deliveryStatus
     * @param deliveryRxJsonStr
     * @param dispenseRxJsonStr
     */
    public RxTcmDispenseInfo handleOrderDeliveryTcm(String deliveryStatus,String deliveryRxJsonStr, String dispenseRxJsonStr) {
        // 发药表的中药处方数据
        RxTcmDispenseInfo rxTcmDeliveryInfo =
                StringUtils.hasText(deliveryRxJsonStr)
                        ? JsonUtil.json2Obj(deliveryRxJsonStr, new TypeReference<RxTcmDispenseInfo>() {})
                        : new RxTcmDispenseInfo();
        if (rxTcmDeliveryInfo == null) {
            throw new BusinessFailException("处方发药数据错误！");
        }
        // 配药表的中药处方数据
        RxTcmDispenseInfo rxTcmDispenseInfo =
                StringUtils.hasText(dispenseRxJsonStr)
                        ? JsonUtil.json2Obj(dispenseRxJsonStr, new TypeReference<RxTcmDispenseInfo>() {})
                        : new RxTcmDispenseInfo();
        if (rxTcmDispenseInfo == null) {
            throw new BusinessFailException("处方配药数据错误！");
        }
        // 本次发药
        Integer currentDeliveryQty = rxTcmDeliveryInfo.getCurrentDeliveryQty();
        if (currentDeliveryQty == null || currentDeliveryQty <= 0) {
            throw new BusinessFailException("本次发药必须为正整数！");
        }
        //发药单中记录的总的待发
        Integer pendingDeliveryQty = rxTcmDeliveryInfo.getDispenseQty();
        if(currentDeliveryQty > pendingDeliveryQty){
            throw new BusinessFailException("本次发药不能大于配药数量！");
        }
        if(DeliveryStatusEnum.PASS.getValue().equals(deliveryStatus)){
            //审核通过 增加已发 减少待发
            // 增加已发
            rxTcmDispenseInfo.setDeliveryQty(rxTcmDispenseInfo.getDeliveryQty() + currentDeliveryQty);
        }else {
            //审核拒绝 增加待配 减少已配
            // 减少已配
            rxTcmDispenseInfo.setDispenseQty(rxTcmDispenseInfo.getDispenseQty() - currentDeliveryQty);
        }
        return rxTcmDispenseInfo;
    }

    /**
     * 查询配药单明细
     * @param orderId 订单ID
     * @param rxIdList 处方集合
     * @return
     */
    public List<OrderDispenseRx> getDispenseRxList(Long orderId, List<Long> rxIdList) {
        OrderDispenseRxExample example = new OrderDispenseRxExample();
        OrderDispenseRxExample.Criteria criteria = example.createCriteria();
        criteria.andOrderIdEqualTo(orderId);
        if(!CollectionUtils.isEmpty(rxIdList)){
            criteria.andRxIdIn(rxIdList);
        }
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        return orderDispenseRxMapper.selectByExample(example);
    }


    /**
     * 查询发药单明细
     * @param orderId
     * @return
     */
    public List<OrderDeliveryDetail> getOrderDeliveryDetailList(Long orderId){
        OrderDeliveryDetailExample example = new OrderDeliveryDetailExample();
        OrderDeliveryDetailExample.Criteria criteria = example.createCriteria();
        criteria.andOrderIdEqualTo(orderId);
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        return orderDeliveryDetailMapper.selectByExample(example);
    }



    /**
     * 创建发药单
     * @param orderDispense
     * @param orderDeliveryDetailList
     */
    @Transactional(rollbackFor = Exception.class)
    public void createDeliveryOrder(OrderDispense orderDispense, List<OrderDeliveryDetail> orderDeliveryDetailList){
        Date createTime = new Date();
        OrderDelivery orderDelivery = buildOrderDelivery(orderDispense,createTime);
        //计算配药数量
        int totalDeliveryQty = orderDeliveryDetailList.stream()
                .mapToInt(OrderDeliveryDetail::getDeliveryQty)
                .sum();
        orderDelivery.setTotalDeliveryQty(totalDeliveryQty);
        orderDeliveryMapper.insertSelective(orderDelivery);
        addOrderDeliveryDetailBatch(
                orderDelivery.getOrderId(),
                orderDelivery.getClinicId(),
                orderDelivery.getCreateUserId(),
                orderDelivery.getCreateBy(),
                createTime,
                orderDeliveryDetailList);
    }

    public OrderDelivery buildOrderDelivery(OrderDispense orderDispense,Date createTime) {
        OrderDelivery orderDelivery = new OrderDelivery();
        orderDelivery.setVisitNo(orderDispense.getVisitNo());
        orderDelivery.setVisitDate(orderDispense.getVisitDate());
        orderDelivery.setOrderNo(orderDispense.getOrderNo());
        orderDelivery.setDoctorId(orderDispense.getDoctorId());
        orderDelivery.setDoctorName(orderDispense.getDoctorName());
        orderDelivery.setDeptId(orderDispense.getDeptId());
        orderDelivery.setDeptName(orderDispense.getDeptName());
        orderDelivery.setDiagnosis(orderDispense.getDiagnosis());
        orderDelivery.setDiagnosisTime(orderDispense.getDiagnosisTime());
        orderDelivery.setPatientId(orderDispense.getPatientId());
        orderDelivery.setPatientName(orderDispense.getPatientName());
        orderDelivery.setPatientGender(orderDispense.getPatientGender());
        orderDelivery.setPatientPhone(orderDispense.getPatientPhone());
        orderDelivery.setIdCard(orderDispense.getIdCard());
        orderDelivery.setAgeYear(orderDispense.getAgeYear());
        orderDelivery.setAgeMonth(orderDispense.getAgeMonth());
        orderDelivery.setSolarBirthday(orderDispense.getSolarBirthday());
        orderDelivery.setLunarBirthday(orderDispense.getLunarBirthday());
        orderDelivery.setWeight(orderDispense.getWeight());
        orderDelivery.setSystolicBp(orderDispense.getSystolicBp());
        orderDelivery.setDiastolicBp(orderDispense.getDiastolicBp());
        orderDelivery.setClinicId(orderDispense.getClinicId());
        orderDelivery.setCreateUserId(orderDispense.getUpdateUserId());
        orderDelivery.setCreateBy(orderDispense.getUpdateBy());
        orderDelivery.setDispenseOrderId(orderDispense.getOrderId());
        orderDelivery.setDispenseUserId(orderDispense.getUpdateUserId());
        orderDelivery.setDispenseUserName(orderDispense.getUpdateBy());
        orderDelivery.setDispenseTime(createTime);
        orderDelivery.setClinicId(orderDispense.getClinicId());
        orderDelivery.setCreateUserId(orderDispense.getUpdateUserId());
        orderDelivery.setCreateBy(orderDispense.getUpdateBy());
        orderDelivery.setOrderNo(IdBuilder.getUniqueId("FY"));
        orderDelivery.setDeliveryStatus(DeliveryStatusEnum.PENDING.getValue());
        orderDelivery.setSortNum(CommonConstant.DEFAULT_1);
        orderDelivery.setIsEnabled(YesOrNoEnum.YES.getValue());
        orderDelivery.setIsDelete(YesOrNoEnum.NO.getValue());
        orderDelivery.setCreateTime(createTime);
        return orderDelivery;
    }

    /**
     * 批量添加发药单
     * @param orderId
     * @param clinicId
     * @param createUserId
     * @param createBy
     * @param createTime
     * @param orderDeliveryDetailList
     */
    @Transactional(rollbackFor = Exception.class)
    public void addOrderDeliveryDetailBatch(Long orderId, Long clinicId, Long createUserId,
                                            String createBy, Date createTime, List<OrderDeliveryDetail> orderDeliveryDetailList) {
        List<OrderDeliveryDetail> deliveryDetailList = new ArrayList<>();
        for(OrderDeliveryDetail orderDeliveryDetail : orderDeliveryDetailList){
            orderDeliveryDetail.setOrderId(orderId);
            orderDeliveryDetail.setClinicId(clinicId);
            orderDeliveryDetail.setIsEnabled(YesOrNoEnum.YES.getValue());
            orderDeliveryDetail.setIsDelete(YesOrNoEnum.NO.getValue());
            orderDeliveryDetail.setCreateUserId(createUserId);
            orderDeliveryDetail.setCreateBy(createBy);
            orderDeliveryDetail.setCreateTime(createTime);
            deliveryDetailList.add(orderDeliveryDetail);
        }
        //批量添加发药单
        specOrderDispenseMapper.addOrderDeliveryDetailBatch(deliveryDetailList);
    }

    /**
     * 完成配药
     */
    @Transactional(rollbackFor = Exception.class)
    public void completeDispense(OrderDispenseDTO orderDispenseDTO){
        OrderDispense dbOrderDispense = getDispenseById(orderDispenseDTO.getOrderId());
        if(dbOrderDispense == null){
            throw new BusinessFailException("配药单不存在");
        }
        if(DispenseStatusEnum.DISPENSED.getValue().equals(dbOrderDispense.getDispenseStatus())){
            throw new BusinessFailException("配药单已经完成了！");
        }
        //APP给过来的处方集合
        List<RxDispenseBase> webRxDispenseList = orderDispenseDTO.getRxList();
        if(CollectionUtils.isEmpty(webRxDispenseList)){
            throw new BusinessFailException("请添加药品的配药数量！");
        }
        //查询配药单
        List<OrderDispenseRx> dbRxDispenseList = getDispenseRxList(orderDispenseDTO.getOrderId(),null);
        if(CollectionUtils.isEmpty(dbRxDispenseList)){
            throw new BusinessFailException("没有找到处方数据！");
        }
        //组装配药数据
        List<OrderDeliveryDetail> updateOrderDeliveryDetailList = handleOrderDispenseDTO(dbRxDispenseList,webRxDispenseList);
        if(CollectionUtils.isEmpty(updateOrderDeliveryDetailList)){
            throw new BusinessFailException("请添加药品的配药数量！");
        }
        //更新人信息
        Long updateUserId = orderDispenseDTO.getUpdateUserId();
        String updateBy = orderDispenseDTO.getUpdateBy();
        Date updateTime = new Date();
        //这里改为从list中判断，不要查库提升效率
        dbOrderDispense.setDispenseStatus(getDispenseStatus(dbRxDispenseList));
        dbOrderDispense.setUpdateUserId(updateUserId);
        dbOrderDispense.setUpdateBy(updateBy);
        dbOrderDispense.setUpdateTime(updateTime);
        orderDispenseMapper.updateByPrimaryKeySelective(dbOrderDispense);
        //批量修改配药单信息
        updateOrderDispenseRxBatch(updateUserId,updateBy,updateTime,dbRxDispenseList);
        //生成发药单
        createDeliveryOrder(dbOrderDispense,updateOrderDeliveryDetailList);
        //统计诊所今日营收
        StatClinicIncomeDaily statClinicIncomeDaily = new StatClinicIncomeDaily();
        statClinicIncomeDaily.setClinicId(dbOrderDispense.getClinicId());
        statClinicIncomeDaily.setDispenseCount(CommonConstant.DEFAULT_1);
        asyncTaskService.asyncSaveOrUpdateClinicIncome(statClinicIncomeDaily);
    }



    public String getDispenseStatus(List<OrderDispenseRx> orderDispenseRxList) {
        for (OrderDispenseRx orderDispenseRx : orderDispenseRxList) {
            if (!DispenseStatusEnum.DISPENSED.getValue().equals(orderDispenseRx.getDispenseStatus())) {
                return DispenseStatusEnum.WAITING.getValue();
            }
        }
        return DispenseStatusEnum.DISPENSED.getValue();
    }

    /**
     * 批量修改配药处方
     * @param updateUserId
     * @param updateBy
     * @param orderDispenseRxList
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateOrderDispenseRxBatch(Long updateUserId,String updateBy, Date updateTime,List<OrderDispenseRx> orderDispenseRxList) {
        for(OrderDispenseRx orderDispenseRx : orderDispenseRxList){
            orderDispenseRx.setUpdateUserId(updateUserId);
            orderDispenseRx.setUpdateBy(updateBy);
            orderDispenseRx.setUpdateTime(updateTime);
        }
        //批量修改配药单
        specOrderDispenseMapper.updateOrderDispenseRxBatch(orderDispenseRxList);
    }


    /**
     * 根据接口给过来的处方数据，生成配药表和发药表的处方数据
     * @param dbRxDispenseList
     * @param webRxDispenseList
     * @return
     */
    public List<OrderDeliveryDetail> handleOrderDispenseDTO(List<OrderDispenseRx> dbRxDispenseList, List<RxDispenseBase> webRxDispenseList) {
        List<OrderDeliveryDetail> updateOrderDeliveryDetailList = new ArrayList<>();
        //把list转为map，提高检索效率
        Map<Long, RxDispenseBase> webRxDispenseMap = webRxDispenseList.stream()
                .collect(Collectors.toMap(RxDispenseBase::getRxId, Function.identity()));
        for(OrderDispenseRx dbOrderDispenseRx : dbRxDispenseList){
            if(DispenseStatusEnum.DISPENSED.getValue().equals(dbOrderDispenseRx.getDispenseStatus())){
                //已经配药完成的不用修改
                continue;
            }
            RxDispenseBase webRxDispenseBase = webRxDispenseMap.get(dbOrderDispenseRx.getRxId());
            if(webRxDispenseBase == null){
                //这个处方不配
                continue;
            }
            String rxType = dbOrderDispenseRx.getRxType();
            if(RxTypeEnum.DRUG.getValue().equals(rxType)){
                OrderDeliveryDetail orderDeliveryDetail = handleOrderDrugDispense(webRxDispenseBase,dbOrderDispenseRx);
                if(orderDeliveryDetail != null){
                    updateOrderDeliveryDetailList.add(orderDeliveryDetail);
                }
            }else if (RxTypeEnum.TCM.getValue().equals(rxType)){
                OrderDeliveryDetail orderDeliveryDetail = handleTcmDispense(webRxDispenseBase,dbOrderDispenseRx);
                if(orderDeliveryDetail != null){
                    updateOrderDeliveryDetailList.add(orderDeliveryDetail);
                }
            }else if (RxTypeEnum.INFUSION.getValue().equals(rxType)){
                OrderDeliveryDetail orderDeliveryDetail = handleInfusionDispense(webRxDispenseBase,dbOrderDispenseRx);
                if(orderDeliveryDetail != null){
                    updateOrderDeliveryDetailList.add(orderDeliveryDetail);
                }
            }
        }
        return updateOrderDeliveryDetailList;
    }


    /**
     * 成药处方
     * @param webRxDispense
     * @param dbOrderDispenseRx
     * @return
     */
    public OrderDeliveryDetail handleOrderDrugDispense(RxDispenseBase webRxDispense, OrderDispenseRx dbOrderDispenseRx){
        //成药处方前端给过来的
        RxDrugDispense webRxDrugDispense = (RxDrugDispense) webRxDispense;
        List<RxDrugDispenseDetail> webRxDrugDispenseDetailList = webRxDrugDispense.getDetailList();
        String dbRxDrugDispenseRxJson = dbOrderDispenseRx.getRxJson();
        // 配药表的成药处方数据
        List<RxDrugDispenseDetail> dbRxDrugDispenseDetailList =
                StringUtils.hasText(dbRxDrugDispenseRxJson)
                        ? JsonUtil.json2Obj(dbRxDrugDispenseRxJson, new TypeReference<List<RxDrugDispenseDetail>>() {})
                        : new ArrayList<>();
        if (CollectionUtils.isEmpty(dbRxDrugDispenseDetailList)) {
            throw new BusinessFailException("处方配药数据错误！");
        }
        List<RxDrugDispenseDetail> updateRxDrugDispenseDetailList = new ArrayList<>();
        //配药完成的数量
        int dispensedCount = CommonConstant.DEFAULT_0;
        int rxDispenseQty = CommonConstant.DEFAULT_0;
        for(RxDrugDispenseDetail dbRxDrugDispenseDetail : dbRxDrugDispenseDetailList){
            //总的待配数量
            Integer dbPendingDispenseQty = dbRxDrugDispenseDetail.getTotalOutQty() - dbRxDrugDispenseDetail.getDispenseQty();
            if(dbPendingDispenseQty <= CommonConstant.DEFAULT_0){
                //配完了
                dispensedCount = dispensedCount +CommonConstant.DEFAULT_1;
                continue;
            }
            RxDrugDispenseDetail webRxDrugDispenseDetail = getRxDrugDispenseDetail(dbRxDrugDispenseDetail.getDrugId(),webRxDrugDispenseDetailList);
            if(webRxDrugDispenseDetail == null){
                //这个药不配
                continue;
            }
            //本次配药
            Integer currentDispenseQty = webRxDrugDispenseDetail.getCurrentDispenseQty();
//            if(StringUtil.isBlank(currentDispenseQty)){
//                //如果不传，默认配置全部的剩余数量
//                currentDispenseQty = dbPendingDispenseQty;
//            }
            if (currentDispenseQty == null) {
                throw new BusinessFailException("请先添加配药数量！");
            }
            if(currentDispenseQty < CommonConstant.DEFAULT_0){
                throw new BusinessFailException("配药数量必须是正整数");
            }
            if(currentDispenseQty == CommonConstant.DEFAULT_0){
                //药品不配
                continue;
            }
            if(currentDispenseQty > dbPendingDispenseQty){
                throw new BusinessFailException("本次配药不能超过总的待配数量");
            }
            //已配数量
            dbRxDrugDispenseDetail.setDispenseQty(dbRxDrugDispenseDetail.getDispenseQty() + currentDispenseQty);
            //当前配药数量设置为0，后边可以继续配
            dbRxDrugDispenseDetail.setCurrentDispenseQty(CommonConstant.DEFAULT_0);
            //本次发 =本次配
            dbRxDrugDispenseDetail.setCurrentDeliveryQty(currentDispenseQty);
            if(dbRxDrugDispenseDetail.getDispenseQty().equals(dbRxDrugDispenseDetail.getTotalOutQty())){
                //加上本次的配完了
                dispensedCount = dispensedCount +CommonConstant.DEFAULT_1;
            }
            updateRxDrugDispenseDetailList.add(dbRxDrugDispenseDetail);
            rxDispenseQty = rxDispenseQty + currentDispenseQty;
        }
        if(dispensedCount == dbRxDrugDispenseDetailList.size()){
            dbOrderDispenseRx.setDispenseStatus(DispenseStatusEnum.DISPENSED.getValue());
        }else {
            dbOrderDispenseRx.setDispenseStatus(DispenseStatusEnum.WAITING.getValue());
        }
        dbOrderDispenseRx.setRxJson(JsonUtil.obj2Json(dbRxDrugDispenseDetailList));
        if(!CollectionUtils.isEmpty(updateRxDrugDispenseDetailList)){
            OrderDeliveryDetail orderDeliveryDetail = new OrderDeliveryDetail();
            BeanUtils.copyProperties(dbOrderDispenseRx,orderDeliveryDetail);
            orderDeliveryDetail.setDeliveryQty(rxDispenseQty);
            orderDeliveryDetail.setRxJson(JsonUtil.obj2Json(updateRxDrugDispenseDetailList));
            return orderDeliveryDetail;
        }
        return null;
    }


    /**
     * 中药处方
     * @param webRxDispense
     * @param dbOrderDispenseRx
     * @return
     */
    public OrderDeliveryDetail handleTcmDispense(RxDispenseBase webRxDispense, OrderDispenseRx dbOrderDispenseRx){
        //前端给过来的数据
        RxTcmDispense webRxTcmDispense = (RxTcmDispense) webRxDispense;
        RxTcmDispenseInfo webRxTcmDispenseTcmInfo = webRxTcmDispense.getTcmInfo();
        // 配药表的成药处方数据
        String dbRxTcmDispenseRxJson = dbOrderDispenseRx.getRxJson();
        RxTcmDispenseInfo dbRxTcmDispenseTcmInfo =
                StringUtils.hasText(dbRxTcmDispenseRxJson)
                        ? JsonUtil.json2Obj(dbRxTcmDispenseRxJson, new TypeReference<RxTcmDispenseInfo>() {})
                        : null;
        if (dbRxTcmDispenseTcmInfo == null) {
            throw new BusinessFailException("处方配药数据错误！");
        }
        //总的待配数量
        Integer dbPendingDispenseQty = dbRxTcmDispenseTcmInfo.getTotalDoses() - dbRxTcmDispenseTcmInfo.getDispenseQty();
        if(dbPendingDispenseQty <= CommonConstant.DEFAULT_0){
            //配完了
            return null;
        }
        if(webRxTcmDispenseTcmInfo == null){
            //不配中药
            return null;
        }
        Integer currentDispenseQty = webRxTcmDispenseTcmInfo.getCurrentDispenseQty();
//        if(StringUtil.isBlank(currentDispenseQty)){
//            //如果不给默认配置剩下的全部待配
//            currentDispenseQty = dbPendingDispenseQty;
//        }
        if (currentDispenseQty == null) {
            throw new BusinessFailException("请先添加配药数量！");
        }
        if(currentDispenseQty < CommonConstant.DEFAULT_0){
            throw new BusinessFailException("配药数量必须是正整数");
        }
        if(currentDispenseQty == CommonConstant.DEFAULT_0){
            //药品不配
            return null;
        }
        //已配数量
        dbRxTcmDispenseTcmInfo.setDispenseQty(dbRxTcmDispenseTcmInfo.getDispenseQty() + currentDispenseQty);
        //当前配药数量设置为0，后边可以继续配
        dbRxTcmDispenseTcmInfo.setCurrentDispenseQty(CommonConstant.DEFAULT_0);
        //本次发=本次配
        dbRxTcmDispenseTcmInfo.setCurrentDeliveryQty(currentDispenseQty);
        if(dbRxTcmDispenseTcmInfo.getDispenseQty().equals(dbRxTcmDispenseTcmInfo.getTotalDoses())){
            //只要有一个药还剩余待配数量，说明处方就只配了一部分
            dbOrderDispenseRx.setDispenseStatus(DispenseStatusEnum.DISPENSED.getValue());
        } else {
            dbOrderDispenseRx.setDispenseStatus(DispenseStatusEnum.WAITING.getValue());
        }
        dbOrderDispenseRx.setRxJson(JsonUtil.obj2Json(dbRxTcmDispenseTcmInfo));
        OrderDeliveryDetail orderDeliveryDetail = new OrderDeliveryDetail();
        BeanUtils.copyProperties(dbOrderDispenseRx,orderDeliveryDetail);
        orderDeliveryDetail.setDeliveryQty(currentDispenseQty);
        orderDeliveryDetail.setRxJson(JsonUtil.obj2Json(dbRxTcmDispenseTcmInfo));
        return orderDeliveryDetail;
    }


    public OrderDeliveryDetail handleInfusionDispense(RxDispenseBase webRxDispense, OrderDispenseRx dbOrderDispenseRx) {
        //输液处方前端给过来的
        RxInfusionDispense webRxInfusionDispense = (RxInfusionDispense) webRxDispense;
        //从前端给出来的输液处方组
        List<RxInfusionDispenseGroup> webRxInfusionDispenseGroupList = webRxInfusionDispense.getGroupList();
        // 配药表的输液处方数据
        String dbRxInfusionDispenseGroupRxJson = dbOrderDispenseRx.getRxJson();
        List<RxInfusionDispenseGroup> dbRxInfusionDispenseGroupList =
                StringUtils.hasText(dbRxInfusionDispenseGroupRxJson)
                        ? JsonUtil.json2Obj(dbRxInfusionDispenseGroupRxJson, new TypeReference<List<RxInfusionDispenseGroup>>() {})
                        : new ArrayList<>();
        if (CollectionUtils.isEmpty(dbRxInfusionDispenseGroupList)) {
            throw new BusinessFailException("处方配药数据错误！");
        }
        List<RxInfusionDispenseGroup> updateRxInfusionDispenseGroupList = new ArrayList<>();
        //完成配药的组的数量
        int groupDispensedCount = CommonConstant.DEFAULT_0;
        int rxDispensedCount = CommonConstant.DEFAULT_0;
        for(RxInfusionDispenseGroup dbRxInfusionDispenseGroup : dbRxInfusionDispenseGroupList){
            RxInfusionDispenseGroup webRxInfusionDispenseGroup = getRxInfusionDispenseGroup(dbRxInfusionDispenseGroup.getGroupName(),webRxInfusionDispenseGroupList);
            //数据库中的输液处方组明细
            List<RxInfusionDispenseGroupDetail> dbRxInfusionDispenseGroupDetailList = dbRxInfusionDispenseGroup.getDetailList();
            if(CollectionUtils.isEmpty(dbRxInfusionDispenseGroupDetailList)){
                throw new BusinessFailException("处方配药数据错误！");
            }
            List<RxInfusionDispenseGroupDetail> updateRxInfusionDispenseGroupDetailList = new ArrayList<>();
            //完成配药的组内的药品数量
            int dispensedCount = CommonConstant.DEFAULT_0;
            for(RxInfusionDispenseGroupDetail dbRxInfusionDispenseGroupDetail : dbRxInfusionDispenseGroupDetailList){
                //总的待配数量
                Integer dbPendingDispenseQty = dbRxInfusionDispenseGroupDetail.getTotalOutQty() - dbRxInfusionDispenseGroupDetail.getDispenseQty();
                if(dbPendingDispenseQty <= CommonConstant.DEFAULT_0){
                    //配完了
                    dispensedCount = dispensedCount + CommonConstant.DEFAULT_1;
                    continue;
                }
                RxInfusionDispenseGroupDetail webRxInfusionDispenseGroupDetail = getRxInfusionDispenseGroupDetail(dbRxInfusionDispenseGroupDetail.getDrugId(),webRxInfusionDispenseGroup);
                if(webRxInfusionDispenseGroupDetail == null){
                    //药品不配
                    continue;
                }
                //本次配药
                Integer currentDispenseQty = webRxInfusionDispenseGroupDetail.getCurrentDispenseQty();
//                if (StringUtil.isBlank(currentDispenseQty)) {
//                    //如果不传就默认配置全部的剩余量
//                    currentDispenseQty = dbPendingDispenseQty;
//                }
                if (currentDispenseQty == null) {
                    throw new BusinessFailException("请先添加配药数量！");
                }
                if(currentDispenseQty < CommonConstant.DEFAULT_0){
                    throw new BusinessFailException("配药数量必须是正整数");
                }
                if(currentDispenseQty == CommonConstant.DEFAULT_0){
                    //药品不配
                    continue;
                }
                if(currentDispenseQty > dbPendingDispenseQty){
                    throw new BusinessFailException("本次配药不能超过总的待配数量");
                }
                //已配数量
                dbRxInfusionDispenseGroupDetail.setDispenseQty(dbRxInfusionDispenseGroupDetail.getDispenseQty() + currentDispenseQty);
                //当前配药数量设置为0，后边可以继续配
                dbRxInfusionDispenseGroupDetail.setCurrentDispenseQty(CommonConstant.DEFAULT_0);
                //本次发 =本次配
                dbRxInfusionDispenseGroupDetail.setCurrentDeliveryQty(currentDispenseQty);
                if(dbRxInfusionDispenseGroupDetail.getDispenseQty().equals(dbRxInfusionDispenseGroupDetail.getTotalOutQty())){
                    //加上本次配的配完了
                    dispensedCount = dispensedCount + CommonConstant.DEFAULT_1;
                }
                updateRxInfusionDispenseGroupDetailList.add(dbRxInfusionDispenseGroupDetail);
                rxDispensedCount = rxDispensedCount + currentDispenseQty;
            }
            if(dispensedCount == dbRxInfusionDispenseGroupDetailList.size()){
                dbRxInfusionDispenseGroup.setDispenseStatus(DispenseStatusEnum.DISPENSED.getValue());
                //代表这一组都配完了
                groupDispensedCount = groupDispensedCount + CommonConstant.DEFAULT_1;
            }
            if(!CollectionUtils.isEmpty(updateRxInfusionDispenseGroupDetailList)){
                RxInfusionDispenseGroup updateRxInfusionDispenseGroup = new RxInfusionDispenseGroup();
                BeanUtils.copyProperties(dbRxInfusionDispenseGroup,updateRxInfusionDispenseGroup);
                updateRxInfusionDispenseGroup.setDetailList(updateRxInfusionDispenseGroupDetailList);
                updateRxInfusionDispenseGroupList.add(updateRxInfusionDispenseGroup);
            }
        }
        if(groupDispensedCount == dbRxInfusionDispenseGroupList.size()){
            dbOrderDispenseRx.setDispenseStatus(DispenseStatusEnum.DISPENSED.getValue());
        }else {
            dbOrderDispenseRx.setDispenseStatus(DispenseStatusEnum.WAITING.getValue());
        }
        dbOrderDispenseRx.setRxJson(JsonUtil.obj2Json(dbRxInfusionDispenseGroupList));
        if(!CollectionUtils.isEmpty(updateRxInfusionDispenseGroupList)){
            OrderDeliveryDetail orderDeliveryDetail = new OrderDeliveryDetail();
            BeanUtils.copyProperties(dbOrderDispenseRx,orderDeliveryDetail);
            orderDeliveryDetail.setDeliveryQty(rxDispensedCount);
            orderDeliveryDetail.setRxJson(JsonUtil.obj2Json(updateRxInfusionDispenseGroupList));
            return orderDeliveryDetail;
        }
        return null;
    }




    public RxInfusionDispenseGroupDetail getRxInfusionDispenseGroupDetail(Long drugId, RxInfusionDispenseGroup rxInfusionDispenseGroup) {
        if(rxInfusionDispenseGroup == null){
            return null;
        }
        List<RxInfusionDispenseGroupDetail> detailList = rxInfusionDispenseGroup.getDetailList();
        return CollectionUtils.isEmpty(detailList) ? null :
                detailList.stream()
                        .filter(item -> drugId.equals(item.getDrugId()))
                        .findFirst()
                        .orElse(null);
    }


    public RxInfusionDispenseGroup getRxInfusionDispenseGroup(String groupName, List<RxInfusionDispenseGroup> rxInfusionDispenseGroupList) {
        return CollectionUtils.isEmpty(rxInfusionDispenseGroupList) ? null :
                rxInfusionDispenseGroupList.stream()
                        .filter(group -> groupName.equals(group.getGroupName()))
                        .findFirst()
                        .orElse(null);

    }

    public RxDrugDispenseDetail getRxDrugDispenseDetail(Long drugId, List<RxDrugDispenseDetail> detailList) {
        return CollectionUtils.isEmpty(detailList) ? null :
                detailList.stream()
                        .filter(detail -> drugId.equals(detail.getDrugId()))
                        .findFirst()
                        .orElse(null);
    }


    /**
     * 新增配药单
     * @param dbChargeOrder 订单信息
     * @param allDispenseItemList 所有的需要开配药单的项目
     */
    @Transactional(rollbackFor = Exception.class)
    public void createDispense(ChargeOrder dbChargeOrder,List<ChargeOrderItem> allDispenseItemList){
        //获取所有的处方ID集合
        List<Long> rxIdList = allDispenseItemList.stream()
                .map(ChargeOrderItem::getItemRefId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        ClinicMedicalDetailVo medicalDetailVo = clinicMedicalService.getMedicalPayRxList(dbChargeOrder.getClinicId(),dbChargeOrder.getVisitNo(),rxIdList);
        if(medicalDetailVo == null || CollectionUtils.isEmpty(medicalDetailVo.getRxList())){
            log.info("新增配药单，没有从病历中找到对应的已支付的处方信息，付款的订单号:{}",dbChargeOrder.getOrderId());
            return;
        }
        OrderDispenseDTO orderDispenseDTO = handleOrderDispenseDTO(medicalDetailVo);
        if(orderDispenseDTO == null){
            return;
        }
        addOrder(orderDispenseDTO);
    }

    /**
     * 组装配药单
     * @param medical
     * @return
     */
    public OrderDispenseDTO handleOrderDispenseDTO(ClinicMedicalDetailVo medical) {
        //组装配药单
        OrderDispenseDTO orderDispense = buildOrderDispense(medical);
        //组装配药单处方
        List<RxDispenseBase> orderDispenseRxList = new ArrayList<>();
        for (RxBase rxBase : medical.getRxList()) {
            RxDispenseBase dispenseRx = new RxDispenseBase();
            dispenseRx.setRxId(rxBase.getRxId());
            dispenseRx.setRxName(rxBase.getRxName());
            dispenseRx.setRxType(rxBase.getRxType());
            dispenseRx.setStorageId(rxBase.getStorageId());
            dispenseRx.setDispenseStatus(DispenseStatusEnum.WAITING.getValue());
            String rxType = rxBase.getRxType();
            if (RxTypeEnum.DRUG.getValue().equals(rxType)) {
                dispenseRx.setRxJson(handleDrugRxJson(rxBase.getRxJson()));
            } else if (RxTypeEnum.INFUSION.getValue().equals(rxType)) {
                dispenseRx.setRxJson(handleInfusionRxJson(rxBase.getRxJson()));
            } else if (RxTypeEnum.TCM.getValue().equals(rxType)) {
                dispenseRx.setRxJson(handleTcmRxJson(rxBase.getRxJson()));
            }
            orderDispenseRxList.add(dispenseRx);
        }
        orderDispense.setRxList(orderDispenseRxList);
        return orderDispense;
    }

    private OrderDispenseDTO buildOrderDispense(ClinicMedicalDetailVo medical) {
        OrderDispenseDTO orderDispense = new OrderDispenseDTO();
        orderDispense.setVisitNo(medical.getVisitNo());
        orderDispense.setVisitDate(medical.getVisitDate());
        orderDispense.setDoctorId(medical.getDoctorId());
        orderDispense.setDoctorName(medical.getDoctorName());
        orderDispense.setDeptId(medical.getDeptId());
        orderDispense.setDeptName(medical.getDeptName());
        orderDispense.setDiagnosis(medical.getDiagnosis());
        orderDispense.setDiagnosisTime(medical.getDiagnosisTime());
        orderDispense.setPatientId(medical.getPatientId());
        orderDispense.setPatientName(medical.getPatientName());
        orderDispense.setPatientGender(medical.getPatientGender());
        orderDispense.setPatientPhone(medical.getPatientPhone());
        orderDispense.setIdCard(medical.getIdCard());
        orderDispense.setAgeYear(medical.getAgeYear());
        orderDispense.setAgeMonth(medical.getAgeMonth());
        orderDispense.setSolarBirthday(medical.getSolarBirthday());
        orderDispense.setLunarBirthday(medical.getLunarBirthday());
        orderDispense.setWeight(medical.getWeight());
        orderDispense.setSystolicBp(medical.getSystolicBp());
        orderDispense.setDiastolicBp(medical.getDiastolicBp());
        orderDispense.setClinicId(medical.getClinicId());
        orderDispense.setCreateUserId(medical.getUpdateUserId());
        orderDispense.setCreateBy(medical.getUpdateBy());
        return orderDispense;
    }

    /**
     * 中药配药单
     * @param rxJsonStr
     * @return
     */
    public String handleTcmRxJson(String rxJsonStr) {
        RxTcmInfo rxTcmInfo = JsonUtil.json2Obj(rxJsonStr, new TypeReference<RxTcmInfo>() {});
        if (rxTcmInfo == null) {
            return null;
        }
        RxTcmDispenseInfo dispense = new RxTcmDispenseInfo();
        BeanUtils.copyProperties(rxTcmInfo, dispense);
        //设置已配
        dispense.setDispenseQty(CommonConstant.DEFAULT_0);
        //设置本次配药
        dispense.setCurrentDispenseQty(CommonConstant.DEFAULT_0);
        //设置已发
        dispense.setDeliveryQty(CommonConstant.DEFAULT_0);
        //设置本次发，没有配好的
        dispense.setCurrentDeliveryQty(CommonConstant.DEFAULT_0);
        return JsonUtil.obj2Json(dispense);
    }

    /**
     * 输液处方配药单
     * @param rxJsonStr
     * @return
     */
    public String handleInfusionRxJson(String rxJsonStr) {
        List<RxInfusionGroup> groupList = JsonUtil.json2Obj(rxJsonStr, new TypeReference<List<RxInfusionGroup>>() {});
        if (CollectionUtils.isEmpty(groupList)) {
            return null;
        }
        List<RxInfusionDispenseGroup> dispenseGroupList = new ArrayList<>();
        for (RxInfusionGroup rxGroup : groupList) {
            RxInfusionDispenseGroup dispenseGroup = new RxInfusionDispenseGroup();
            dispenseGroup.setDispenseStatus(DispenseStatusEnum.WAITING.getValue());
            BeanUtils.copyProperties(rxGroup, dispenseGroup);
            List<RxInfusionGroupDetail> detailList = rxGroup.getDetailList();
            if (CollectionUtils.isEmpty(detailList)) {
                continue;
            }
            List<RxInfusionDispenseGroupDetail> resultDetailList = new ArrayList<>();
            for (RxInfusionGroupDetail detail : detailList) {
                RxInfusionDispenseGroupDetail dispenseDetail = new RxInfusionDispenseGroupDetail();
                BeanUtils.copyProperties(detail, dispenseDetail);
                //已配数量
                dispenseDetail.setDispenseQty(CommonConstant.DEFAULT_0);
                //本次配置数量
                dispenseDetail.setCurrentDispenseQty(CommonConstant.DEFAULT_0);
                //设置已发
                dispenseDetail.setDeliveryQty(CommonConstant.DEFAULT_0);
                //设置本次发，没有配好的
                dispenseDetail.setCurrentDeliveryQty(CommonConstant.DEFAULT_0);
                resultDetailList.add(dispenseDetail);
            }
            dispenseGroup.setDetailList(resultDetailList);
            dispenseGroupList.add(dispenseGroup);
        }
        return JsonUtil.obj2Json(dispenseGroupList);
    }

    /**
     * 成药发药单
     * @param rxJsonStr
     * @return
     */
    public String handleDrugRxJson(String rxJsonStr) {
        List<RxDrugDetail> detailList = JsonUtil.json2Obj(rxJsonStr, new TypeReference<List<RxDrugDetail>>() {});
        if (CollectionUtils.isEmpty(detailList)) {
            return null;
        }
        List<RxDrugDispenseDetail> dispenseDetail = new ArrayList<>();
        for (RxDrugDetail rxDrugDetail : detailList) {
            RxDrugDispenseDetail dispense = new RxDrugDispenseDetail();
            BeanUtils.copyProperties(rxDrugDetail, dispense);
            //设置已配
            dispense.setDispenseQty(CommonConstant.DEFAULT_0);
            //设置本次配药
            dispense.setCurrentDispenseQty(CommonConstant.DEFAULT_0);
            //设置已发
            dispense.setDeliveryQty(CommonConstant.DEFAULT_0);
            //设置本次发，没有配好的
            dispense.setCurrentDeliveryQty(CommonConstant.DEFAULT_0);
            dispenseDetail.add(dispense);
        }
        return JsonUtil.obj2Json(dispenseDetail);
    }




    /**
     * 提取出来成药的药品ID
     * @param rxList
     * @return
     */
    public List<Long> getDrugIdList(List<RxBase> rxList) {
        List<Long> drugIdList = rxList.stream()
                .flatMap(rxBase -> {
                    String rxType = rxBase.getRxType();
                    if (RxTypeEnum.DRUG.getValue().equals(rxType)) {
                        RxDrug rxDrug = (RxDrug) rxBase;
                        return Optional.ofNullable(rxDrug.getDetailList()).orElse(Collections.emptyList()).stream()
                                .map(RxDrugDetail::getDrugId);
                    } else if (RxTypeEnum.INFUSION.getValue().equals(rxType)) {
                        RxInfusion rxInfusion = (RxInfusion) rxBase;
                        return Optional.ofNullable(rxInfusion.getGroupList()).orElse(Collections.emptyList()).stream()
                                .flatMap(group -> Optional.ofNullable(group.getDetailList()).orElse(Collections.emptyList()).stream())
                                .map(RxInfusionGroupDetail::getDrugId);
                    }
                    return Stream.empty();
                })
                .collect(Collectors.toList());
        return drugIdList;
    }


    /**
     * 保存配药单
     * @param orderDispense
     */
    @Transactional(rollbackFor = Exception.class)
    public void addOrder(OrderDispenseDTO orderDispense) {
        OrderDispense dbOrderDispense = getOrderDispenseByVisitNo(orderDispense.getVisitNo());
        if(dbOrderDispense == null){
            //生成配药单
            orderDispense.setOrderNo(IdBuilder.getUniqueId("ZH"));
            orderDispense.setDispenseStatus(DispenseStatusEnum.WAITING.getValue());
            orderDispense.setSortNum(CommonConstant.DEFAULT_1);
            orderDispense.setIsEnabled(YesOrNoEnum.YES.getValue());
            orderDispense.setIsDelete(YesOrNoEnum.NO.getValue());
            orderDispense.setCreateTime(new Date());
            orderDispenseMapper.insertSelective(orderDispense);
            addOrderDispenseRxBatch(
                    orderDispense.getOrderId(),
                    orderDispense.getClinicId(),
                    orderDispense.getCreateUserId(),
                    orderDispense.getCreateBy(),
                    orderDispense.getRxList());
        }else {
            //又新的支付项目进来了，需要重置配药状态
            dbOrderDispense.setDispenseStatus(DispenseStatusEnum.WAITING.getValue());
            dbOrderDispense.setUpdateUserId(orderDispense.getCreateUserId());
            dbOrderDispense.setUpdateBy(orderDispense.getCreateBy());
            dbOrderDispense.setUpdateTime(new Date());
            orderDispenseMapper.updateByPrimaryKeySelective(dbOrderDispense);
            addOrderDispenseRxBatch(
                    dbOrderDispense.getOrderId(),
                    dbOrderDispense.getClinicId(),
                    dbOrderDispense.getUpdateUserId(),
                    dbOrderDispense.getUpdateBy(),
                    orderDispense.getRxList());
        }

    }


    /**
     * 批量添加配药处方
     * @param orderId
     * @param clinicId
     * @param createUserId
     * @param createBy
     * @param orderDispenseRxList
     */
    @Transactional(rollbackFor = Exception.class)
    public void addOrderDispenseRxBatch(Long orderId,Long clinicId,Long createUserId,String createBy, List<RxDispenseBase> orderDispenseRxList) {
        Date now = new Date();
        List<OrderDispenseRx> dispenseRxList = new ArrayList<>();
        for(RxDispenseBase rxDispenseBase : orderDispenseRxList){
            OrderDispenseRx orderDispenseRx = new OrderDispenseRx();
            orderDispenseRx.setRxId(rxDispenseBase.getRxId());
            orderDispenseRx.setRxName(rxDispenseBase.getRxName());
            orderDispenseRx.setRxType(rxDispenseBase.getRxType());
            orderDispenseRx.setStorageId(rxDispenseBase.getStorageId());
            orderDispenseRx.setDispenseStatus(DispenseStatusEnum.WAITING.getValue());
            orderDispenseRx.setRxJson(rxDispenseBase.getRxJson());
            if(StringUtil.isBlank(orderDispenseRx.getRxJson())){
                // 根据 rxType 类型添加到对应的列表中
                if (RxTypeEnum.DRUG.getValue().equals(rxDispenseBase.getRxType())) {
                    RxDrugDispense rxDrugDispense = (RxDrugDispense) rxDispenseBase;
                    orderDispenseRx.setRxJson(JsonUtil.obj2Json(rxDrugDispense.getDetailList()));
                } else if (RxTypeEnum.INFUSION.getValue().equals(rxDispenseBase.getRxType())) {
                    RxInfusionDispense rxInfusionDispense = (RxInfusionDispense) rxDispenseBase;
                    orderDispenseRx.setRxJson(JsonUtil.obj2Json(rxInfusionDispense.getGroupList()));
                }else if (RxTypeEnum.TCM.getValue().equals(rxDispenseBase.getRxType())) {
                    RxTcmDispense rxTcmDispense = (RxTcmDispense) rxDispenseBase;
                    orderDispenseRx.setRxJson(JsonUtil.obj2Json(rxTcmDispense.getTcmInfo()));
                }
            }
            orderDispenseRx.setOrderId(orderId);
            orderDispenseRx.setClinicId(clinicId);
            orderDispenseRx.setIsEnabled(YesOrNoEnum.YES.getValue());
            orderDispenseRx.setIsDelete(YesOrNoEnum.NO.getValue());
            orderDispenseRx.setCreateUserId(createUserId);
            orderDispenseRx.setCreateBy(createBy);
            orderDispenseRx.setCreateTime(now);
            dispenseRxList.add(orderDispenseRx);
        }
        //批量添加配药单
        specOrderDispenseMapper.addOrderDispenseRxBatch(dispenseRxList);
    }

    /**
     * 根据诊号查询配药单
     * @param visitNo
     * @return
     */
    public OrderDispense getOrderDispenseByVisitNo(String visitNo){
        OrderDispenseExample example = new OrderDispenseExample();
        OrderDispenseExample.Criteria criteria = example.createCriteria();
        criteria.andVisitNoEqualTo(visitNo);
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        List<OrderDispense> orderDispenseList = orderDispenseMapper.selectByExample(example);
        return CollectionUtils.isEmpty(orderDispenseList) ? null : orderDispenseList.get(0);
    }


    /**
     * 分页查询发药单明细列表
     * @param orderId 发药单ID
     * @param pageNo 页码
     * @param pageSize 每页条数
     * @return 分页结果
     */
    public PageInfo<OrderDeliveryDetail> getDeliveryDetailListByCondition(Long orderId, Integer pageNo, Integer pageSize) {
        OrderDeliveryDetailExample example = new OrderDeliveryDetailExample();
        OrderDeliveryDetailExample.Criteria criteria = example.createCriteria();
        if (orderId != null) {
            criteria.andOrderIdEqualTo(orderId);
        }
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        Long totalCount = orderDeliveryDetailMapper.countByExample(example);
        if (totalCount == null || totalCount == 0) {
            return PageInfo.build();
        }
        example.setOffset(PageUtils.getOffset(pageNo, pageSize));
        example.setLimit(pageSize);
        example.setOrderByClause("create_time desc");
        List<OrderDeliveryDetail> list = orderDeliveryDetailMapper.selectByExample(example);
        return new PageInfo<>(totalCount, list);
    }

    /**
     * 添加发药单明细
     * @param detail 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void addDeliveryDetail(OrderDeliveryDetail detail) {
        validateDeliveryDetail(detail);
        detail.setIsDelete(YesOrNoEnum.NO.getValue());
        detail.setIsEnabled(YesOrNoEnum.YES.getValue());
        detail.setCreateTime(new Date());
        orderDeliveryDetailMapper.insertSelective(detail);
    }

    /**
     * 校验发药单明细参数
     * @param detail 实体
     */
    public void validateDeliveryDetail(OrderDeliveryDetail detail) {
        // TODO: 添加具体校验逻辑
    }

    /**
     * 根据ID获取发药单明细详情
     * @param detailId 主键
     * @return 实体
     */
    public OrderDeliveryDetail getDeliveryDetailById(Long detailId) {
        if (detailId == null) {
            return null;
        }
        OrderDeliveryDetail detail = orderDeliveryDetailMapper.selectByPrimaryKey(detailId);
        if (detail == null || YesOrNoEnum.YES.getValue().equals(detail.getIsDelete())) {
            return null;
        }
        return detail;
    }

    /**
     * 修改发药单明细
     * @param detail 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateDeliveryDetail(OrderDeliveryDetail detail) {
        validateDeliveryDetail(detail);
        OrderDeliveryDetail dbDetail = getDeliveryDetailById(detail.getDetailId());
        if (dbDetail == null) {
            throw new BusinessFailException("发药单明细不存在");
        }
        detail.setUpdateTime(new Date());
        orderDeliveryDetailMapper.updateByPrimaryKeySelective(detail);
    }

    /**
     * 删除发药单明细（逻辑删除）
     * @param detail 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteDeliveryDetail(OrderDeliveryDetail detail) {
        OrderDeliveryDetail dbDetail = getDeliveryDetailById(detail.getDetailId());
        if (dbDetail == null) {
            throw new BusinessFailException("发药单明细不存在");
        }
        dbDetail.setIsDelete(YesOrNoEnum.YES.getValue());
        dbDetail.setUpdateUserId(detail.getUpdateUserId());
        dbDetail.setUpdateBy(detail.getUpdateBy());
        dbDetail.setUpdateTime(new Date());
        orderDeliveryDetailMapper.updateByPrimaryKeySelective(dbDetail);
    }

    /**
     * 启用发药单明细
     * @param detail 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void enableDeliveryDetail(OrderDeliveryDetail detail) {
        OrderDeliveryDetail dbDetail = getDeliveryDetailById(detail.getDetailId());
        if (dbDetail == null) {
            throw new BusinessFailException("发药单明细不存在");
        }
        if (YesOrNoEnum.YES.getValue().equals(dbDetail.getIsEnabled())) {
            return;
        }
        dbDetail.setIsEnabled(YesOrNoEnum.YES.getValue());
        dbDetail.setUpdateUserId(detail.getUpdateUserId());
        dbDetail.setUpdateBy(detail.getUpdateBy());
        dbDetail.setUpdateTime(new Date());
        orderDeliveryDetailMapper.updateByPrimaryKeySelective(dbDetail);
    }

    /**
     * 停用发药单明细
     * @param detail 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void disableDeliveryDetail(OrderDeliveryDetail detail) {
        OrderDeliveryDetail dbDetail = getDeliveryDetailById(detail.getDetailId());
        if (dbDetail == null) {
            throw new BusinessFailException("发药单明细不存在");
        }
        if (YesOrNoEnum.NO.getValue().equals(dbDetail.getIsEnabled())) {
            return;
        }
        dbDetail.setIsEnabled(YesOrNoEnum.NO.getValue());
        dbDetail.setUpdateUserId(detail.getUpdateUserId());
        dbDetail.setUpdateBy(detail.getUpdateBy());
        dbDetail.setUpdateTime(new Date());
        orderDeliveryDetailMapper.updateByPrimaryKeySelective(dbDetail);
    }

    /**
     * 分页查询发药单列表
     * @param clinicId 诊所ID
     * @param pageNo 页码
     * @param pageSize 每页条数
     * @return 分页结果
     */
    public PageInfo<OrderDelivery> getDeliveryListByCondition(Long clinicId, Integer pageNo, Integer pageSize) {
        OrderDeliveryExample example = new OrderDeliveryExample();
        OrderDeliveryExample.Criteria criteria = example.createCriteria();
        if (clinicId != null) {
            criteria.andClinicIdEqualTo(clinicId);
        }
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        Long totalCount = orderDeliveryMapper.countByExample(example);
        if (totalCount == null || totalCount == 0) {
            return PageInfo.build();
        }
        example.setOffset(PageUtils.getOffset(pageNo, pageSize));
        example.setLimit(pageSize);
        example.setOrderByClause("create_time desc");
        List<OrderDelivery> list = orderDeliveryMapper.selectByExample(example);
        return new PageInfo<>(totalCount, list);
    }

    /**
     * 添加发药单
     * @param delivery 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void addDelivery(OrderDelivery delivery) {
        validateDelivery(delivery);
        delivery.setIsDelete(YesOrNoEnum.NO.getValue());
        delivery.setIsEnabled(YesOrNoEnum.YES.getValue());
        delivery.setCreateTime(new Date());
        orderDeliveryMapper.insertSelective(delivery);
    }

    /**
     * 校验发药单参数
     * @param delivery 实体
     */
    public void validateDelivery(OrderDelivery delivery) {
        // TODO 补充参数校验逻辑
    }

    /**
     * 根据ID获取发药单详情
     * @param orderId 主键
     * @return 实体
     */
    public OrderDelivery getDeliveryById(Long orderId) {
        if (StringUtil.isBlank(orderId)) {
            return null;
        }
        OrderDelivery delivery = orderDeliveryMapper.selectByPrimaryKey(orderId);
        if (delivery == null || YesOrNoEnum.YES.getValue().equals(delivery.getIsDelete())) {
            return null;
        }
        return delivery;
    }

    /**
     * 修改发药单
     * @param delivery 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateDelivery(OrderDelivery delivery) {
        validateDelivery(delivery);
        OrderDelivery dbDelivery = getDeliveryById(delivery.getOrderId());
        if (dbDelivery == null) {
            throw new BusinessFailException("发药单不存在");
        }
        delivery.setUpdateTime(new Date());
        orderDeliveryMapper.updateByPrimaryKeySelective(delivery);
    }

    /**
     * 删除发药单（逻辑删除）
     * @param delivery 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteDelivery(OrderDelivery delivery) {
        OrderDelivery dbDelivery = getDeliveryById(delivery.getOrderId());
        if (dbDelivery == null) {
            throw new BusinessFailException("发药单不存在");
        }
        dbDelivery.setIsDelete(YesOrNoEnum.YES.getValue());
        dbDelivery.setUpdateUserId(delivery.getUpdateUserId());
        dbDelivery.setUpdateBy(delivery.getUpdateBy());
        dbDelivery.setUpdateTime(new Date());
        orderDeliveryMapper.updateByPrimaryKeySelective(dbDelivery);
    }

    /**
     * 启用发药单
     * @param delivery 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void enableDelivery(OrderDelivery delivery) {
        OrderDelivery dbDelivery = getDeliveryById(delivery.getOrderId());
        if (dbDelivery == null) {
            throw new BusinessFailException("发药单不存在");
        }
        if (YesOrNoEnum.YES.getValue().equals(dbDelivery.getIsEnabled())) {
            return;
        }
        dbDelivery.setIsEnabled(YesOrNoEnum.YES.getValue());
        dbDelivery.setUpdateUserId(delivery.getUpdateUserId());
        dbDelivery.setUpdateBy(delivery.getUpdateBy());
        dbDelivery.setUpdateTime(new Date());
        orderDeliveryMapper.updateByPrimaryKeySelective(dbDelivery);
    }

    /**
     * 停用发药单
     * @param delivery 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void disableDelivery(OrderDelivery delivery) {
        OrderDelivery dbDelivery = getDeliveryById(delivery.getOrderId());
        if (dbDelivery == null) {
            throw new BusinessFailException("发药单不存在");
        }
        if (YesOrNoEnum.NO.getValue().equals(dbDelivery.getIsEnabled())) {
            return;
        }
        dbDelivery.setIsEnabled(YesOrNoEnum.NO.getValue());
        dbDelivery.setUpdateUserId(delivery.getUpdateUserId());
        dbDelivery.setUpdateBy(delivery.getUpdateBy());
        dbDelivery.setUpdateTime(new Date());
        orderDeliveryMapper.updateByPrimaryKeySelective(dbDelivery);
    }

    /**
     * 分页查询配药单明细列表
     * @param orderId 配药单ID
     * @param pageNo 页码
     * @param pageSize 每页条数
     * @return 分页结果
     */
    public PageInfo<OrderDispenseRx> getDispenseRxListByCondition(Long orderId, Integer pageNo, Integer pageSize) {
        OrderDispenseRxExample example = new OrderDispenseRxExample();
        OrderDispenseRxExample.Criteria criteria = example.createCriteria();
        if (orderId != null) {
            criteria.andOrderIdEqualTo(orderId);
        }
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        Long totalCount = orderDispenseRxMapper.countByExample(example);
        if (totalCount == null || totalCount == 0) {
            return PageInfo.build();
        }
        example.setOffset(PageUtils.getOffset(pageNo, pageSize));
        example.setLimit(pageSize);
        example.setOrderByClause("create_time desc");
        List<OrderDispenseRx> list = orderDispenseRxMapper.selectByExample(example);
        return new PageInfo<>(totalCount, list);
    }

    /**
     * 添加配药单明细
     * @param orderDispenseRx 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void addDispenseRx(OrderDispenseRx orderDispenseRx) {
        validateDispenseDetail(orderDispenseRx);
        orderDispenseRx.setIsDelete(YesOrNoEnum.NO.getValue());
        orderDispenseRx.setIsEnabled(YesOrNoEnum.YES.getValue());
        orderDispenseRx.setCreateTime(new Date());
        orderDispenseRxMapper.insertSelective(orderDispenseRx);
    }

    /**
     * 校验配药单明细参数
     * @param orderDispenseRx 实体
     */
    public void validateDispenseDetail(OrderDispenseRx orderDispenseRx) {
        // TODO 添加必要的校验逻辑
    }

    /**
     * 根据ID获取配药单明细详情
     * @param rxId 主键
     * @return 实体
     */
    public OrderDispenseRx getDispenseDetailById(Long rxId) {
        if (StringUtil.isBlank(rxId)) {
            return null;
        }
        OrderDispenseRx orderDispenseRx = orderDispenseRxMapper.selectByPrimaryKey(rxId);
        if (orderDispenseRx == null || YesOrNoEnum.YES.getValue().equals(orderDispenseRx.getIsDelete())) {
            return null;
        }
        return orderDispenseRx;
    }

    /**
     * 修改配药单明细
     * @param orderDispenseRx 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateDispenseDetail(OrderDispenseRx orderDispenseRx) {
        validateDispenseDetail(orderDispenseRx);
        OrderDispenseRx dbDetail = getDispenseDetailById(orderDispenseRx.getRxId());
        if (dbDetail == null) {
            throw new BusinessFailException("配药单明细不存在");
        }
        orderDispenseRx.setUpdateTime(new Date());
        orderDispenseRxMapper.updateByPrimaryKeySelective(orderDispenseRx);
    }

    /**
     * 删除配药单明细（逻辑删除）
     * @param detail 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteDispenseDetail(OrderDispenseRx detail) {
        OrderDispenseRx dbDetail = getDispenseDetailById(detail.getRxId());
        if (dbDetail == null) {
            throw new BusinessFailException("配药单明细不存在");
        }
        dbDetail.setIsDelete(YesOrNoEnum.YES.getValue());
        dbDetail.setUpdateUserId(detail.getUpdateUserId());
        dbDetail.setUpdateBy(detail.getUpdateBy());
        dbDetail.setUpdateTime(new Date());
        orderDispenseRxMapper.updateByPrimaryKeySelective(dbDetail);
    }

    /**
     * 启用配药单明细
     * @param detail 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void enableDispenseDetail(OrderDispenseRx detail) {
        OrderDispenseRx dbDetail = getDispenseDetailById(detail.getRxId());
        if (dbDetail == null) {
            throw new BusinessFailException("配药单明细不存在");
        }
        if (YesOrNoEnum.YES.getValue().equals(dbDetail.getIsEnabled())) {
            return;
        }
        dbDetail.setIsEnabled(YesOrNoEnum.YES.getValue());
        dbDetail.setUpdateUserId(detail.getUpdateUserId());
        dbDetail.setUpdateBy(detail.getUpdateBy());
        dbDetail.setUpdateTime(new Date());
        orderDispenseRxMapper.updateByPrimaryKeySelective(dbDetail);
    }

    /**
     * 停用配药单明细
     * @param detail 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void disableDispenseDetail(OrderDispenseRx detail) {
        OrderDispenseRx dbDetail = getDispenseDetailById(detail.getRxId());
        if (dbDetail == null) {
            throw new BusinessFailException("配药单明细不存在");
        }
        if (YesOrNoEnum.NO.getValue().equals(dbDetail.getIsEnabled())) {
            return;
        }
        dbDetail.setIsEnabled(YesOrNoEnum.NO.getValue());
        dbDetail.setUpdateUserId(detail.getUpdateUserId());
        dbDetail.setUpdateBy(detail.getUpdateBy());
        dbDetail.setUpdateTime(new Date());
        orderDispenseRxMapper.updateByPrimaryKeySelective(dbDetail);
    }

    /**
     * 分页查询配药单列表
     * @param clinicId 诊所ID
     * @param pageNo 页码
     * @param pageSize 每页条数
     * @return 分页结果
     */
    public PageInfo<OrderDispense> getDispenseListByCondition(Long clinicId, Integer pageNo, Integer pageSize) {
        OrderDispenseExample example = new OrderDispenseExample();
        OrderDispenseExample.Criteria criteria = example.createCriteria();
        if (clinicId != null) {
            criteria.andClinicIdEqualTo(clinicId);
        }
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        Long totalCount = orderDispenseMapper.countByExample(example);
        if (totalCount == null || totalCount == 0) {
            return PageInfo.build();
        }
        example.setOffset(PageUtils.getOffset(pageNo, pageSize));
        example.setLimit(pageSize);
        example.setOrderByClause("create_time desc");
        List<OrderDispense> list = orderDispenseMapper.selectByExample(example);
        return new PageInfo<>(totalCount, list);
    }

    /**
     * 添加配药单
     * @param orderDispense 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void addDispense(OrderDispense orderDispense) {
        validateDispense(orderDispense);
        orderDispense.setIsDelete(YesOrNoEnum.NO.getValue());
        orderDispense.setIsEnabled(YesOrNoEnum.YES.getValue());
        orderDispense.setCreateTime(new Date());
        orderDispenseMapper.insertSelective(orderDispense);
    }

    /**
     * 校验配药单参数
     * @param orderDispense 实体
     */
    public void validateDispense(OrderDispense orderDispense) {
        // TODO 校验逻辑补充
    }

    /**
     * 根据ID获取配药单详情
     * @param orderId 主键
     * @return 实体
     */
    public OrderDispense getDispenseById(Long orderId) {
        if (StringUtil.isBlank(orderId)) {
            return null;
        }
        OrderDispense dispense = orderDispenseMapper.selectByPrimaryKey(orderId);
        if (dispense == null || YesOrNoEnum.YES.getValue().equals(dispense.getIsDelete())) {
            return null;
        }
        return dispense;
    }

    /**
     * 修改配药单
     * @param dispense 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateDispense(OrderDispense dispense) {
        validateDispense(dispense);
        OrderDispense dbDispense = getDispenseById(dispense.getOrderId());
        if (dbDispense == null) {
            throw new BusinessFailException("配药单不存在");
        }
        dispense.setUpdateTime(new Date());
        orderDispenseMapper.updateByPrimaryKeySelective(dispense);
    }

    /**
     * 删除配药单（逻辑删除）
     * @param dispense 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteDispense(OrderDispense dispense) {
        OrderDispense dbDispense = getDispenseById(dispense.getOrderId());
        if (dbDispense == null) {
            throw new BusinessFailException("配药单不存在");
        }
        dbDispense.setIsDelete(YesOrNoEnum.YES.getValue());
        dbDispense.setUpdateUserId(dispense.getUpdateUserId());
        dbDispense.setUpdateBy(dispense.getUpdateBy());
        dbDispense.setUpdateTime(new Date());
        orderDispenseMapper.updateByPrimaryKeySelective(dbDispense);
    }

    /**
     * 启用配药单
     * @param dispense 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void enableDispense(OrderDispense dispense) {
        OrderDispense dbDispense = getDispenseById(dispense.getOrderId());
        if (dbDispense == null) {
            throw new BusinessFailException("配药单不存在");
        }
        if (YesOrNoEnum.YES.getValue().equals(dbDispense.getIsEnabled())) {
            return;
        }
        dbDispense.setIsEnabled(YesOrNoEnum.YES.getValue());
        dbDispense.setUpdateUserId(dispense.getUpdateUserId());
        dbDispense.setUpdateBy(dispense.getUpdateBy());
        dbDispense.setUpdateTime(new Date());
        orderDispenseMapper.updateByPrimaryKeySelective(dbDispense);
    }

    /**
     * 停用配药单
     * @param dispense 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void disableDispense(OrderDispense dispense) {
        OrderDispense dbDispense = getDispenseById(dispense.getOrderId());
        if (dbDispense == null) {
            throw new BusinessFailException("配药单不存在");
        }
        if (YesOrNoEnum.NO.getValue().equals(dbDispense.getIsEnabled())) {
            return;
        }
        dbDispense.setIsEnabled(YesOrNoEnum.NO.getValue());
        dbDispense.setUpdateUserId(dispense.getUpdateUserId());
        dbDispense.setUpdateBy(dispense.getUpdateBy());
        dbDispense.setUpdateTime(new Date());
        orderDispenseMapper.updateByPrimaryKeySelective(dbDispense);
    }

}
